package com.cf.user.core.part.wx;

import com.cf.constant.EnumReturnCode;
import com.cf.exception.BizException;
import com.cf.mapper.BeanMapper;
import com.cf.user.core.EnumLoginChannel;
import com.cf.user.login.model.ThirdPartUser;
import com.cf.user.login.model.UserInfo;
import com.cf.user.login.service.UserInfoService;
import com.cf.user.login.service.UserPartService;
import com.cf.util.HttpUtil;
import com.cf.util.ObjectJsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Map;

/**
 * game-server-WxUserService
 *
 * @author <a href="2428922347@qq.com">Zhu mingming</a>
 * @info
 * @since 2018/5/22 下午 04:25
 */
public class WxUserService {

    @Autowired
    private WxSmallAppProperty wxSmallAppProperty;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private UserPartService userPartService;

    @Autowired
    private BeanMapper beanMapper;

    private WxSessionKey getWxUserInfo(String code) {
        String s = HttpUtil.get(wxSmallAppProperty.getUserOpenIdUrl(code));
        try {
            Map wxRtMap = ObjectJsonUtil.toObject(s, Map.class);
            Object errCode = wxRtMap.get("errcode");
            if (errCode == null) {
                return new WxSessionKey((String) wxRtMap.get("session_key"), (String) wxRtMap.get("openid"));
            } else {
                throw new BizException(EnumReturnCode.ERROR.getCode(), "微信授权失败:获取openId失败");
            }
        } catch (Exception e) {
            throw new BizException(EnumReturnCode.ERROR.getCode(), "微信授权失败:获取openId失败", e);
        }
    }

    @Transactional
    public UserInfo xcxLogin(String code, String encryptedData, String ivo) {
        if (!StringUtils.hasLength(code)) {
            throw new BizException(EnumReturnCode.ERROR.getCode(), "获取微信小程序SESSION_KEY的参数CODE缺失！");
        }
        WxSessionKey wxSessionKey = getWxUserInfo(code);
        String sessionKey = wxSessionKey.getSessionKey();
        if (!StringUtils.hasLength(sessionKey))
            throw new BizException(EnumReturnCode.ERROR.getCode(), "获取微信小程序SESSION_KEY异常！");

        WxUserInfo wxUserInfo = getWxUserInfo(encryptedData, sessionKey, ivo);

        if (wxUserInfo == null) {
            throw new BizException(EnumReturnCode.ERROR.getCode(), "解密微信小程序数据异常，解密失败！");
        }

        ThirdPartUser thirdPartUser = userPartService.findThirdPartUser(EnumLoginChannel.WXSGAME.getChannel(), wxUserInfo.getUnionId());
        if (thirdPartUser == null) {
            //todo 这边需要用分布式锁，当前版本先忽略掉
            return saveUser(wxUserInfo);
        } else {
            long userId = thirdPartUser.getUserId();
            UserInfo userInfo = userInfoService.getUserInfo(String.valueOf(userId));
            if (userInfo == null) {
                throw new BizException(EnumReturnCode.ERROR.getCode(), "用户数据缺失！");
            } else {
                return userInfo;
            }
        }
    }

    private UserInfo saveUser(WxUserInfo wxUserInfo) {
        UserInfo userInfo = new UserInfo();
        beanMapper.map(wxUserInfo, userInfo);
        UserInfo ui = userInfoService.addUser(userInfo);
        ThirdPartUser thirdPartUser = userPartService.addThirdUser(ui.getId(), wxUserInfo.getOpenId(), wxUserInfo.getUnionId(), EnumLoginChannel.WXSGAME.getChannel());
        return userInfo;
    }

    private WxUserInfo getWxUserInfo(String encryptedDataStr, String sessionKey, String ivo) {
        try {
            AES aes = new AES();
            byte[] resultByte = aes.decrypt(Base64Utils.decode(encryptedDataStr.getBytes("utf-8")), Base64Utils.decode(sessionKey.getBytes("utf-8")), Base64Utils.decode(ivo.getBytes("utf-8")));
            if (null != resultByte && resultByte.length > 0) {
                String userInfo = new String(resultByte, "UTF-8");
                Map map = ObjectJsonUtil.toObject(userInfo, Map.class);
                return new WxUserInfo((String) map.get("nickName"),
                        (Integer) map.get("gender"),
                        (String) map.get("city"),
                        (String) map.get("province"),
                        (String) map.get("avatarUrl"),
                        (String) map.get("country"),
                        "",
                        (String) map.get("openId"),
                        (String) map.get("unionId")
                );
            }
            throw new BizException(EnumReturnCode.ERROR.getCode(), "解密数据失败！");
        } catch (Exception e) {
            throw new BizException(EnumReturnCode.ERROR.getCode(), "解密数据失败！");
        }
    }


    public static void main(String[] args) throws Exception {
        String encryptedData = "cXl8RKOr0jmOGXe5yTkLb6LPazKG2u5KW6tII5t0mFwJhnnIhTSyVsVhcdXr+vUZ9z/gkHiuYzd4w3c4NTY973UbUiL6JC9I5dV+RWOOsSp3BBytvpgrrhXapQJzrZmps8nVviF5nsNs5qb+IsgJmYRQaEBMAfZZs8O1NuBuLy528nJ1CcDkqmfpkT5r5FLpI9YzRH8tNMyxJYKxeXpsuNpnlcP/2hwOClV5X9WYbs/YlJlhC8k5mMXXTblFP2FL/J9IHABZOfQTJvrUQ8LgAbp53Ar/xfWzE0qYz3tEJ+pNjj2uN40i5MBd+x8/Oo9BxyJpXCb4AeKRZLFngQnxA8Mz5NEpcQWh/WkoRHe+NPxCJDPixhZIy1yejDrRPyTxRjPujPs4qqmcla4mc3qwcHOiqNUKSQxheS39Iv/MRE3EdXnxQErSKWaIEuj2Vj0eOJ/yvQcLU1xUtU1mlh8PPjoWLbuVMT8zj3VCblBj8vnp4r9BtNtGHnz4BDjjfgNzGaBTKXRScJ6Z/jwe38kBYw==";
        String sessionKey = "vVJL17+39+xr/A0uRUWOSg==";
        String iv = "H4oTk5k7HEYIRWw0ENp7Ew==";
        WxUserService wxUserService = new WxUserService();
        WxUserInfo wxUserInfo = wxUserService.getWxUserInfo(encryptedData, sessionKey, iv);
        System.out.println(wxUserInfo);
    }
}
